package com.muchenx.controller;

import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.muchenx.db.CodeCache;
import com.muchenx.entity.Template;
import com.muchenx.service.AutoCodeGenerator;
import com.muchenx.util.UIComponentUtil;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CenterViewController {

    @FXML
    public ScrollPane scrollPane;
    @FXML
    private TableView<Template> tableView;

    @FXML
    private TableColumn<Template, String> templateFileClassPath;

    @FXML
    private TableColumn<Template, Boolean> enable;

    private final ObservableList<Template> tableData = FXCollections.observableArrayList();

    // 初始化
    @FXML
    private void initialize() {
        // 将列与数据模型中的属性关联
        templateFileClassPath.setCellValueFactory(new PropertyValueFactory<>("templateFileClassPath"));
        enable.setCellValueFactory(new PropertyValueFactory<>("enable"));
        enable.setCellFactory(col -> new CheckBoxTableCell(new SimpleBooleanProperty(true)));

        Optional.ofNullable(getClass().getResource("/templates")).ifPresent(parent -> {
            Stream.of(Objects.requireNonNull(new File(parent.getPath()).listFiles()))
                    .forEach(file -> tableData.add(new Template(file.getName().replace(".ftl", ""), true)));
        });

        // 将数据绑定到表格中
        tableView.setItems(tableData);
    }

    @FXML
    public void generateCode(ActionEvent actionEvent) {
        Map<OutputFile, String> mapEnableTemplates = mapEnableTemplates();
        if (mapEnableTemplates.isEmpty()) {
            UIComponentUtil.errorAlert("至少需要选择一个模板！");
            return;
        }
        VBox vBox = new VBox();
        vBox.setFillWidth(true);
        vBox.setPrefWidth(300);
        vBox.setPrefHeight(200);
        final TextField tableTextField = UIComponentUtil.textField("请输入生成模板代码的表名(多张表以,分隔)");
        final TextField pkgTextField = UIComponentUtil.textField("请输入子包名(如user)为一级");

        vBox.getChildren().addAll(
                UIComponentUtil.wrapTextField(tableTextField, "表名"),
                UIComponentUtil.wrapTextField(pkgTextField, "实体子包名"));
        Alert alert = UIComponentUtil.createCustomConfirm("代码生成", 300, 150, vBox);
        // 修改按钮描述
        alert.getDialogPane().getButtonTypes().setAll(
                new ButtonType("生成代码", ButtonBar.ButtonData.OK_DONE),
                new ButtonType("取消操作", ButtonBar.ButtonData.CANCEL_CLOSE));
        alert.showAndWait().ifPresent(type -> {
            String generatedPath;
            if (ButtonType.OK.getButtonData().equals(type.getButtonData())) {
                String tableName = tableTextField.getText();
                if (StringUtils.isEmpty(tableName)) {
                    UIComponentUtil.errorAlert("数据库表名不能为空！");
                    return;
                }
                if (StringUtils.isEmpty(CodeCache.parentPackage)) {
                    UIComponentUtil.errorAlert("父包名不能为空，请到【设置>代码】进行配置！");
                    return;
                }
                Class<?> superCls = null;
                try {
                    try {
                        superCls = Class.forName(CodeCache.parentEntity);
                    } catch (Exception ignored) {
                    }
                    String subPkg = pkgTextField.getText();
                    if (StringUtils.isNotEmpty(subPkg)
                            && subPkg.startsWith(CodeCache.parentPackage)) {
                        subPkg = subPkg.substring(CodeCache.parentPackage.length());
                        subPkg = (subPkg.startsWith(".")) ? subPkg.substring(1) : subPkg;
                    }
                    generatedPath = AutoCodeGenerator.create()
                            .generate(tableName,
                                    superCls,
                                    CodeCache.parentPackage,
                                    subPkg,
                                    mapEnableTemplates);
                } catch (Throwable e) {
                    UIComponentUtil.errorAlert("代码已生异常: " + e.getMessage());
                    return;
                }
                UIComponentUtil.infoAlert("代码已生成到: " + generatedPath);
                return;
            }
            UIComponentUtil.errorAlert("已取消操作！");
        });

    }

    private Map<OutputFile, String> mapEnableTemplates() {
        return tableData.stream().filter(Template::getEnable)
                .collect(Collectors.toMap(this::matchesKey, Template::getTemplateFileClassPath));
    }

    private OutputFile matchesKey(Template file) {
        return Arrays.stream(OutputFile.values())
                .filter(item -> file.getTemplateFileClassPath().startsWith(item.getTemplate()))
                .findFirst().orElse(null);
    }

    /**
     * 带选择框的TableCell
     */
    public static class CheckBoxTableCell extends TableCell<Template, Boolean> {
        private final CheckBox checkBox;
        private final BooleanProperty property;

        public CheckBoxTableCell(BooleanProperty property) {
            this.property = property;
            this.checkBox = new CheckBox();
            this.checkBox.selectedProperty().addListener((obs, oldValue, newValue) -> {
                if (isEditing()) {
                    commitEdit(newValue);
                }
                property.setValue(newValue);

                // 同步修改com.muchenx.CenterViewController.data[i].enable的值
                if (getTableRow() != null) {
                    int selectIndex = getTableRow().getIndex();
                    ObservableList<Template> data = getTableView().getItems();
                    if (selectIndex >= 0 && selectIndex < data.size()) {
                        data.get(selectIndex).setEnable(newValue);
                    }
                }
            });
            this.setGraphic(checkBox);
            this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            this.setEditable(true);
        }

        @Override
        protected void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || item == null) {
                setGraphic(null);
            } else {
                checkBox.setSelected(item);
                setGraphic(checkBox);
            }
        }

        @Override
        public void startEdit() {
            super.startEdit();
            if (!isEmpty()) {
                checkBox.requestFocus();
            }
        }

        @Override
        public void commitEdit(Boolean newValue) {
            super.commitEdit(newValue);
            if (property != null) {
                property.setValue(newValue);
            }
        }

        @Override
        public void cancelEdit() {
            super.cancelEdit();
            if (property != null) {
                checkBox.setSelected(property.get());
            }
        }
    }
}